#ifndef __FSM_H__
#define __FSM_H__

#define SINGLE_STATE_MAX_EVENT 6
#define STATE_EVENT_BUFFER_MAX 4

typedef int FSM_EVENT_ID;
typedef int FSM_STATE_ID;

typedef struct event_param_st{
    FSM_EVENT_ID id;
    union{
        int i;
    }data;

    int lock;
    int f,r;
    int countdown;
    FSM_EVENT_ID buffer[STATE_EVENT_BUFFER_MAX];
}FSM_EVENT;

typedef void (*FSM_FUNC)(FSM_EVENT *);

typedef struct state_event_st{
    FSM_FUNC func;
    FSM_EVENT_ID event;
    FSM_STATE_ID state;
}FSM_STATE_EVENT;

typedef struct state_st{
    FSM_STATE_ID id;
    char *name;
    FSM_FUNC enter_func;
    FSM_FUNC exit_func;
    FSM_FUNC default_func;
    FSM_STATE_EVENT event_table[SINGLE_STATE_MAX_EVENT];
}FSM_STATE;

typedef FSM_STATE STATE_TABLE[];
typedef FSM_STATE *STATE_TABLE_PTR;

typedef struct fsm_st{
    FSM_STATE_ID state_id;
    FSM_FUNC default_func;
    STATE_TABLE_PTR state_tables;
}FSM;

#define END_EVENT_ID 6
#define END_STATE_ID -1

#define BEGIN_FSM_STATE_TABLE(state_stable) static STATE_TABLE (state_stable)={
#define BEGIN_STATE(id,name,enter_func,exit_func,default_func) {(id),(name),(enter_func),(exit_func),(default_func),{
#define STATE_EVENT_ITEM(func,event,state) {(func),(event),(state)},
#define END_STATE(id) {NULL,END_EVENT_ID,END_STATE_ID}}},
#define END_FSM_STATE_TABLE(state_stable) {END_STATE_ID,NULL,NULL,NULL,NULL,NULL}};

void fsm_function(FSM *fsm, FSM_EVENT *event);

void event_buffer_push(FSM_EVENT *event, FSM_EVENT_ID);
FSM_EVENT_ID event_buffer_pop(FSM_EVENT *event);

/* GRAMB FSM */

typedef enum{
    GRAMB_STATE_ERROR,
    GRAMB_STATE_INIT,
    GRAMB_STATE_STOP,
    GRAMB_STATE_RUNNING
}GRAMB_STATE;

typedef enum{
    GRAMB_EVENT_ERROR,
    GRAMB_EVENT_RESET,
    GRAMB_EVENT_RESUME,
    GRAMB_EVENT_STOP
}GRAMB_EVENT;

#endif /* __FSM_H__ */
